/**
 * 解析颜色字符串，将其转换为 RGB 数组
 * @param {string} color 颜色字符串，可以是 #ABC、#AABBCC 或 r,g,b 格式
 */
export const parseColor = (color: string = ''): number[] => {
  if (typeof color !== 'string') {
    throw new TypeError('Color should be a string!')
  }

  // 匹配 #AABBCC 格式的颜色
  const hexMatch = /^#?([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i.exec(color)
  if (hexMatch) {
    // 使用 slice(1) 提取匹配的 RGB 组件，并将其转换为数字
    return hexMatch.slice(1).map((c) => Number.parseInt(c, 16))
  }

  // 匹配 #ABC 格式的颜色，将每个字符重复一次
  const hexMatchShort = /^#?([\da-f])([\da-f])([\da-f])$/i.exec(color)
  if (hexMatchShort) {
    return hexMatchShort.slice(1).map((c) => Number.parseInt(c + c, 16))
  }

  // 匹配 r,g,b 格式的颜色，通过逗号分隔
  if (color.includes(',')) {
    return color.split(',').map((p) => Number.parseInt(p.trim(), 10))
  }

  // 如果没有匹配任何有效的格式，抛出错误
  throw new Error('Invalid color format! Use #ABC, #AABBCC, or r,g,b')
}

/**
 * 将 RGB 数组转换为十六进制颜色字符串
 * @param {number[]} rgbValues 表示颜色的 RGB 数组 [r, g, b]
 */
export const hexValue = (rgbValues: number[]): string => {
  return `#${rgbValues
    .map((c) => c.toString(16).padStart(2, '0').toUpperCase()) // 保证每个值至少有两位，并转换为大写
    .join('')}`
}

/**
 * 为 RGB 数组应用色调（提亮）
 * @param {number[]} rgbValues 表示颜色的 RGB 数组 [r, g, b]
 * @param {number} intensity 色调强度，取值范围为 0-1
 */
export const tint = (rgbValues: number[], intensity: number): number[] => {
  return rgbValues.map((c) => Math.round(c + (255 - c) * intensity))
}

/**
 * 为 RGB 数组应用阴影（加暗）
 * @param {number[]} rgbValues 表示颜色的 RGB 数组 [r, g, b]
 * @param {number} intensity 阴影强度，取值范围为 0-1
 */
export const shade = (rgbValues: number[], intensity: number): number[] => {
  return rgbValues.map((c) => Math.round(c * intensity))
}

/**
 * 生成带有色调的函数，用于对 RGB 数组应用指定强度的色调
 * @param {number} intensity 色调强度，取值范围为 0-1
 */
export const withTint = (intensity: number) => {
  return (rgbValues: number[]): number[] => tint(rgbValues, intensity)
}

/**
 * 生成带有阴影的函数，用于对 RGB 数组应用指定强度的阴影
 * @param {number} intensity 阴影强度，取值范围为 0-1
 */
export const withShade = (intensity: number) => {
  return (rgbValues: number[]): number[] => shade(rgbValues, intensity)
}

/**
 * 定义颜色的不同变体
 */
export const colorVariants = {
  50: withTint(0.95), // 应用 95% 强度的浅色调，生成非常浅的颜色
  100: withTint(0.9), // 应用 90% 强度的浅色调
  200: withTint(0.75), // 应用 75% 强度的浅色调
  300: withTint(0.6), // 应用 60% 强度的浅色调
  400: withTint(0.3), // 应用 30% 强度的浅色调，接近原始色
  500: (c: number[]) => c, // 原始颜色，不做任何变化
  600: withShade(0.9), // 应用 90% 强度的深色阴影，略微变暗
  700: withShade(0.6), // 应用 60% 强度的深色阴影
  800: withShade(0.45), // 应用 45% 强度的深色阴影
  900: withShade(0.3), // 应用 30% 强度的深色阴影
  950: withShade(0.2) // 应用 20% 强度的深色阴影，颜色最暗
}

/**
 * 根据给定的颜色生成不同的色调和阴影变体。
 * @param color
 * @param variants
 */
export const getColors = (color: string, variants: Record<string, (c: number[]) => number[]> = colorVariants): Record<string, string> => {
  const colors: Record<string, string> = {} // 用于存储生成的变体颜色结果
  const rgbValues = parseColor(color) // 解析颜色字符串为 RGB 组件数组 [r, g, b]
  // 遍历传入的变体对象，为每个变体生成对应的颜色
  for (const [name, fn] of Object.entries(variants)) {
    colors[name] = hexValue(fn(rgbValues)) // 调用变体函数对 RGB 组件进行处理，并转换为十六进制颜色字符串
  }
  return colors // 返回包含多个颜色变体的对象
}
